home *** CD-ROM | disk | FTP | other *** search
/ 10,000 Great Games / 10,000 Great Games.iso / Product / 66 / data1.cab / Source_Files / Src / Blit.cpp < prev    next >
C/C++ Source or Header  |  2000-01-16  |  16KB  |  653 lines

  1. #include "stdafx.h"
  2.  
  3. void colormapped_blit(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, RECT *srcrect, char *colormap)
  4. {
  5.     DDSURFACEDESC2 destsurf, srcsurf;
  6.     BYTE *d, *s;
  7.     
  8.     ASSERT(colormap != 0);
  9.  
  10.     // Lock surfaces
  11.     
  12.     srcsurf.dwSize = sizeof(srcsurf);    
  13.     
  14.     while (!draw_ok(src->Lock(srcrect, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  15.         
  16.     destsurf.dwSize = sizeof(destsurf);
  17.     
  18.     while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  19.             
  20.     // Get pointers
  21.         
  22.     d = (BYTE *)destsurf.lpSurface;
  23.     s = (BYTE *)srcsurf.lpSurface;
  24.  
  25.     // Get size of area to write
  26.  
  27.     int w = destrect->right - destrect->left,
  28.          h = destrect->bottom - destrect->top;
  29.  
  30.     int line_offset_src = srcsurf.lPitch - w,
  31.         line_offset_dest = destsurf.lPitch - w;
  32.         
  33.     // Do the blit
  34.  
  35.     __asm
  36.     {
  37.         mov ebx, colormap
  38.  
  39.         mov esi, s
  40.         mov edi, d
  41.         
  42.         // Make sure high order of eax is clear
  43.  
  44.         xor eax, eax
  45.  
  46.         mov edx, h
  47.     blit_loop_y:
  48.  
  49.         mov ecx, w
  50.     blit_loop_x:
  51.  
  52.         // Get source pixel shift it 8 bits to the left and add destination pixel
  53.  
  54.         lodsb
  55.         shl ax, 8
  56.         add al, [edi]
  57.  
  58.         // Lookup value from table and store it
  59.  
  60.         mov al, [ebx + eax]
  61.         stosb
  62.  
  63.         loop blit_loop_x
  64.  
  65.         // Goto next line
  66.  
  67.         add esi, line_offset_src
  68.         add edi, line_offset_dest
  69.     
  70.         dec edx
  71.         jnz blit_loop_y
  72.     }
  73.     
  74.     // Unlock surfaces
  75.         
  76.     src->Unlock(srcrect);
  77.     dest->Unlock(destrect);
  78. }
  79.  
  80. void rotated_blit(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, int mx, int my, fix angle, fix scale)
  81. {
  82.     // Define:    (x,y) is a point in the source surface,
  83.     //            (u,v) is a point in the destination surface,
  84.     //            (0,0) corresponds to the center of the image in both surfaces.
  85.     //
  86.     // A point in the source surface is then given as:
  87.     //
  88.     // (x,y) = 1/scale * ((cos angle, sin angle), (-sin angle, cos angle)) (u,v)
  89.     
  90.     DDSURFACEDESC2 destsurf, srcsurf;
  91.     BYTE *d, *s;
  92.  
  93.     ASSERT(scale != (fix)0);
  94.     
  95.     // Lock surfaces
  96.     
  97.     srcsurf.dwSize = sizeof(srcsurf);    
  98.     
  99.     while (!draw_ok(src->Lock(0, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  100.         
  101.     destsurf.dwSize = sizeof(destsurf);
  102.     
  103.     while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  104.             
  105.     // Get destination pointer
  106.         
  107.     d = (BYTE *)destsurf.lpSurface;    
  108.         
  109.     // Get size of area to write
  110.         
  111.     int w = destrect->right - destrect->left,
  112.          h = destrect->bottom - destrect->top;
  113.         
  114.     // Compute some frequently used variables
  115.     
  116.     fix cos_angle_over_scale = cos(angle) / scale,
  117.         sin_angle_over_scale = sin(angle) / scale;
  118.  
  119.     // Compute (dx,dy) for (du,dv)=(1,0)
  120.  
  121.     #define dx_du    cos_angle_over_scale
  122.     #define    dy_du    -sin_angle_over_scale
  123.  
  124.     // Compute (dx,dy) for (du,dv)=(0,1)
  125.  
  126.     #define dx_dv    sin_angle_over_scale
  127.     #define    dy_dv    cos_angle_over_scale
  128.  
  129.     // Compute the first pixel in the destination surface (su, sv)
  130.  
  131.     int su = destrect->left - mx,
  132.         sv = destrect->top - my;
  133.  
  134.     // Compute the first pixel in the source surface (sx, sy)
  135.  
  136.     fix sx = cos_angle_over_scale * su + sin_angle_over_scale * sv,
  137.         sy = cos_angle_over_scale * sv - sin_angle_over_scale * su;
  138.  
  139.     // Transform to the source surface coordinates
  140.  
  141.     sx += srcsurf.dwWidth / 2;
  142.     sy += srcsurf.dwHeight / 2;
  143.     
  144.     // Do the blit
  145.             
  146.     for (int v = 0; v < h; v++)
  147.     {    
  148.         // (x,y) is the current pixel that has to be copied
  149.         
  150.         fix x = sx,
  151.             y = sy;
  152.  
  153.         for (int u = 0; u < w; u++, d++)
  154.         {
  155.             // (ix,iy) is the integer location of the current pixel
  156.  
  157.             int ix = (int)x, iy = (int)y;
  158.  
  159.             // Check if (ix,iy) is in the image
  160.  
  161.             if (ix >= 0 && ix < (int)srcsurf.dwWidth && iy >= 0 && iy < (int)srcsurf.dwHeight)
  162.             {
  163.                 // Compute the pixels location in memory
  164.                 
  165.                 s = ((BYTE *)srcsurf.lpSurface) + iy * srcsurf.lPitch + ix;
  166.  
  167.                 // If not mask_color then write the pixel
  168.  
  169.                 if (*s != mask_color)
  170.                     *d = *s;
  171.             }
  172.  
  173.             // Update (x,y)
  174.  
  175.             x += dx_du;
  176.             y += dy_du;
  177.         }            
  178.         
  179.         // Update the destination pointer to the next scanline
  180.  
  181.         d += destsurf.lPitch - w;        
  182.  
  183.         // (sx,sy) is moved one scanline
  184.  
  185.         sx += dx_dv;
  186.         sy += dy_dv;
  187.     }
  188.         
  189.     // Unlock surfaces
  190.         
  191.     src->Unlock(0);
  192.     dest->Unlock(destrect);
  193. }
  194.  
  195. void rotated_colormapped_blit(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, int mx, int my, fix angle, fix scale, char *colormap)
  196. {
  197.     // Define:    (x,y) is a point in the source surface,
  198.     //            (u,v) is a point in the destination surface,
  199.     //            (0,0) corresponds to the center of the image in both surfaces.
  200.     //
  201.     // A point in the source surface is then given as:
  202.     //
  203.     // (x,y) = 1/scale * ((cos angle, sin angle), (-sin angle, cos angle)) (u,v)
  204.     
  205.     DDSURFACEDESC2 destsurf, srcsurf;
  206.     BYTE *d, *s;
  207.  
  208.     ASSERT(colormap != 0 && scale != (fix)0);
  209.  
  210.     // Lock surfaces
  211.     
  212.     srcsurf.dwSize = sizeof(srcsurf);    
  213.     
  214.     while (!draw_ok(src->Lock(0, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  215.         
  216.     destsurf.dwSize = sizeof(destsurf);
  217.     
  218.     while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  219.             
  220.     // Get destination pointer
  221.         
  222.     d = (BYTE *)destsurf.lpSurface;    
  223.         
  224.     // Get size of area to write
  225.         
  226.     int w = destrect->right - destrect->left,
  227.          h = destrect->bottom - destrect->top;
  228.         
  229.     // Compute some frequently used variables
  230.     
  231.     fix cos_angle_over_scale = cos(angle) / scale,
  232.         sin_angle_over_scale = sin(angle) / scale;
  233.  
  234.     // Compute (dx,dy) for (du,dv)=(1,0)
  235.  
  236.     #define dx_du    cos_angle_over_scale
  237.     #define    dy_du    -sin_angle_over_scale
  238.  
  239.     // Compute (dx,dy) for (du,dv)=(0,1)
  240.  
  241.     #define dx_dv    sin_angle_over_scale
  242.     #define    dy_dv    cos_angle_over_scale
  243.  
  244.     // Compute the first pixel in the destination surface (su, sv)
  245.  
  246.     int su = destrect->left - mx,
  247.         sv = destrect->top - my;
  248.  
  249.     // Compute the first pixel in the source surface (sx, sy)
  250.  
  251.     fix sx = cos_angle_over_scale * su + sin_angle_over_scale * sv,
  252.         sy = cos_angle_over_scale * sv - sin_angle_over_scale * su;
  253.  
  254.     // Transform to the source surface coordinates
  255.  
  256.     sx += srcsurf.dwWidth / 2;
  257.     sy += srcsurf.dwHeight / 2;
  258.     
  259.     // Do the blit
  260.             
  261.     for (int v = 0; v < h; v++)
  262.     {    
  263.         // (x,y) is the current pixel that has to be copied
  264.         
  265.         fix x = sx,
  266.             y = sy;
  267.  
  268.         for (int u = 0; u < w; u++, d++)
  269.         {
  270.             // (ix,iy) is the integer location of the current pixel
  271.  
  272.             int ix = (int)x, iy = (int)y;
  273.  
  274.             // Check if (ix,iy) is in the image
  275.  
  276.             if (ix >= 0 && ix < (int)srcsurf.dwWidth && iy >= 0 && iy < (int)srcsurf.dwHeight)
  277.             {
  278.                 // Compute the pixels location in memory
  279.                 
  280.                 s = ((BYTE *)srcsurf.lpSurface) + iy * srcsurf.lPitch + ix;
  281.  
  282.                 // Write the pixel
  283.  
  284.                 *d = colormap[*d + (*s << 8)];
  285.             }
  286.  
  287.             // Update (x,y)
  288.  
  289.             x += dx_du;
  290.             y += dy_du;
  291.         }            
  292.         
  293.         // Update the destination pointer to the next scanline
  294.  
  295.         d += destsurf.lPitch - w;        
  296.  
  297.         // (sx,sy) is moved one scanline
  298.  
  299.         sx += dx_dv;
  300.         sy += dy_dv;
  301.     }
  302.         
  303.     // Unlock surfaces
  304.         
  305.     src->Unlock(0);
  306.     dest->Unlock(destrect);
  307. }
  308.  
  309. void rotated_blit16(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, int mx, int my, fix angle, fix scale)
  310. {
  311.     // Define:    (x,y) is a point in the source surface,
  312.     //            (u,v) is a point in the destination surface,
  313.     //            (0,0) corresponds to the center of the image in both surfaces.
  314.     //
  315.     // A point in the source surface is then given as:
  316.     //
  317.     // (x,y) = 1/scale * ((cos angle, sin angle), (-sin angle, cos angle)) (u,v)
  318.     
  319.     DDSURFACEDESC2 destsurf, srcsurf;
  320.     BYTE *d, *s;
  321.     
  322.     ASSERT(scale != (fix)0);
  323.  
  324.     // Lock surfaces
  325.     
  326.     srcsurf.dwSize = sizeof(srcsurf);    
  327.     
  328.     while (!draw_ok(src->Lock(0, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  329.         
  330.     destsurf.dwSize = sizeof(destsurf);
  331.     
  332.     while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  333.             
  334.     // Get destination pointer
  335.         
  336.     d = (BYTE *)destsurf.lpSurface;    
  337.         
  338.     // Get size of area to write
  339.         
  340.     int w = destrect->right - destrect->left,
  341.          h = destrect->bottom - destrect->top;
  342.         
  343.     // Compute some frequently used variables
  344.     
  345.     fix cos_angle_over_scale = cos(angle) / scale,
  346.         sin_angle_over_scale = sin(angle) / scale;
  347.  
  348.     // Compute (dx,dy) for (du,dv)=(1,0)
  349.  
  350.     #define dx_du    cos_angle_over_scale
  351.     #define    dy_du    -sin_angle_over_scale
  352.  
  353.     // Compute (dx,dy) for (du,dv)=(0,1)
  354.  
  355.     #define dx_dv    sin_angle_over_scale
  356.     #define    dy_dv    cos_angle_over_scale
  357.  
  358.     // Compute the first pixel in the destination surface (su, sv)
  359.  
  360.     int su = destrect->left - mx,
  361.         sv = destrect->top - my;
  362.  
  363.     // Compute the first pixel in the source surface (sx, sy)
  364.  
  365.     fix sx = cos_angle_over_scale * su + sin_angle_over_scale * sv,
  366.         sy = cos_angle_over_scale * sv - sin_angle_over_scale * su;
  367.  
  368.     // Transform to the source surface coordinates
  369.  
  370.     sx += srcsurf.dwWidth / 2;
  371.     sy += srcsurf.dwHeight / 2;
  372.     
  373.     // Do the blit
  374.             
  375.     for (int v = 0; v < h; v++)
  376.     {    
  377.         // (x,y) is the current pixel that has to be copied
  378.         
  379.         fix x = sx,
  380.             y = sy;
  381.  
  382.         for (int u = 0; u < w; u++, d += 2)
  383.         {
  384.             // (ix,iy) is the integer location of the current pixel
  385.  
  386.             int ix = (int)x, iy = (int)y;
  387.  
  388.             // Check if (ix,iy) is in the image
  389.  
  390.             if (ix >= 0 && ix < (int)srcsurf.dwWidth && iy >= 0 && iy < (int)srcsurf.dwHeight)
  391.             {
  392.                 // Compute the pixels location in memory
  393.                 
  394.                 s = ((BYTE *)srcsurf.lpSurface) + iy * srcsurf.lPitch + (ix << 1);
  395.  
  396.                 // If not mask_color then write the pixel
  397.  
  398.                 if (*(WORD *)s != (WORD)mask_color)
  399.                     *(WORD *)d = *(WORD *)s;
  400.             }
  401.  
  402.             // Update (x,y)
  403.  
  404.             x += dx_du;
  405.             y += dy_du;
  406.         }            
  407.         
  408.         // Update the destination pointer to the next scanline
  409.  
  410.         d += destsurf.lPitch - (w << 1);        
  411.  
  412.         // (sx,sy) is moved one scanline
  413.  
  414.         sx += dx_dv;
  415.         sy += dy_dv;
  416.     }
  417.         
  418.     // Unlock surfaces
  419.         
  420.     src->Unlock(0);
  421.     dest->Unlock(destrect);
  422. }
  423.  
  424. void rotated_blit24(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, int mx, int my, fix angle, fix scale)
  425. {
  426.     // Define:    (x,y) is a point in the source surface,
  427.     //            (u,v) is a point in the destination surface,
  428.     //            (0,0) corresponds to the center of the image in both surfaces.
  429.     //
  430.     // A point in the source surface is then given as:
  431.     //
  432.     // (x,y) = 1/scale * ((cos angle, sin angle), (-sin angle, cos angle)) (u,v)
  433.     
  434.     DDSURFACEDESC2 destsurf, srcsurf;
  435.     BYTE *d, *s;
  436.     
  437.     ASSERT(scale != (fix)0);
  438.  
  439.     // Lock surfaces
  440.     
  441.     srcsurf.dwSize = sizeof(srcsurf);    
  442.     
  443.     while (!draw_ok(src->Lock(0, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  444.         
  445.     destsurf.dwSize = sizeof(destsurf);
  446.     
  447.     while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  448.             
  449.     // Get destination pointer
  450.         
  451.     d = (BYTE *)destsurf.lpSurface;    
  452.         
  453.     // Get size of area to write
  454.         
  455.     int w = destrect->right - destrect->left,
  456.          h = destrect->bottom - destrect->top;
  457.         
  458.     // Compute some frequently used variables
  459.     
  460.     fix cos_angle_over_scale = cos(angle) / scale,
  461.         sin_angle_over_scale = sin(angle) / scale;
  462.  
  463.     // Compute (dx,dy) for (du,dv)=(1,0)
  464.  
  465.     #define dx_du    cos_angle_over_scale
  466.     #define    dy_du    -sin_angle_over_scale
  467.  
  468.     // Compute (dx,dy) for (du,dv)=(0,1)
  469.  
  470.     #define dx_dv    sin_angle_over_scale
  471.     #define    dy_dv    cos_angle_over_scale
  472.  
  473.     // Compute the first pixel in the destination surface (su, sv)
  474.  
  475.     int su = destrect->left - mx,
  476.         sv = destrect->top - my;
  477.  
  478.     // Compute the first pixel in the source surface (sx, sy)
  479.  
  480.     fix sx = cos_angle_over_scale * su + sin_angle_over_scale * sv,
  481.         sy = cos_angle_over_scale * sv - sin_angle_over_scale * su;
  482.  
  483.     // Transform to the source surface coordinates
  484.  
  485.     sx += srcsurf.dwWidth / 2;
  486.     sy += srcsurf.dwHeight / 2;
  487.     
  488.     // Do the blit
  489.             
  490.     for (int v = 0; v < h; v++)
  491.     {    
  492.         // (x,y) is the current pixel that has to be copied
  493.         
  494.         fix x = sx,
  495.             y = sy;
  496.  
  497.         for (int u = 0; u < w; u++, d += 3)
  498.         {
  499.             // (ix,iy) is the integer location of the current pixel
  500.  
  501.             int ix = (int)x, iy = (int)y;
  502.  
  503.             // Check if (ix,iy) is in the image
  504.  
  505.             if (ix >= 0 && ix < (int)srcsurf.dwWidth && iy >= 0 && iy < (int)srcsurf.dwHeight)
  506.             {
  507.                 // Compute the pixels location in memory
  508.                 
  509.                 s = ((BYTE *)srcsurf.lpSurface) + iy * srcsurf.lPitch + (ix << 1) + ix;
  510.  
  511.                 // If not mask_color then write the pixel
  512.  
  513.                 if ((*(DWORD *)s & 0xffffff) != (DWORD)mask_color)
  514.                     *(WORD *)d = *(WORD *)s, d[2] = s[2];
  515.             }
  516.  
  517.             // Update (x,y)
  518.  
  519.             x += dx_du;
  520.             y += dy_du;
  521.         }            
  522.         
  523.         // Update the destination pointer to the next scanline
  524.  
  525.         d += destsurf.lPitch - (w << 1) - w;        
  526.  
  527.         // (sx,sy) is moved one scanline
  528.  
  529.         sx += dx_dv;
  530.         sy += dy_dv;
  531.     }
  532.         
  533.     // Unlock surfaces
  534.         
  535.     src->Unlock(0);
  536.     dest->Unlock(destrect);
  537. }
  538.  
  539. void rotated_blit32(LPDIRECTDRAWSURFACE4 dest, RECT *destrect, LPDIRECTDRAWSURFACE4 src, int mx, int my, fix angle, fix scale)
  540. {
  541.     // Define:    (x,y) is a point in the source surface,
  542.     //            (u,v) is a point in the destination surface,
  543.     //            (0,0) corresponds to the center of the image in both surfaces.
  544.     //
  545.     // A point in the source surface is then given as:
  546.     //
  547.     // (x,y) = 1/scale * ((cos angle, sin angle), (-sin angle, cos angle)) (u,v)
  548.     
  549.     DDSURFACEDESC2 destsurf, srcsurf;
  550.     BYTE *d, *s;
  551.  
  552.     ASSERT(scale != (fix)0);
  553.  
  554.     // Lock surfaces
  555.     
  556.     srcsurf.dwSize = sizeof(srcsurf);    
  557.     
  558.     while (!draw_ok(src->Lock(0, &srcsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  559.         
  560.     destsurf.dwSize = sizeof(destsurf);
  561.     
  562.     while (!draw_ok(dest->Lock(destrect, &destsurf, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0)));
  563.             
  564.     // Get destination pointer
  565.         
  566.     d = (BYTE *)destsurf.lpSurface;    
  567.         
  568.     // Get size of area to write
  569.         
  570.     int w = destrect->right - destrect->left,
  571.          h = destrect->bottom - destrect->top;
  572.         
  573.     // Compute some frequently used variables
  574.     
  575.     fix cos_angle_over_scale = cos(angle) / scale,
  576.         sin_angle_over_scale = sin(angle) / scale;
  577.  
  578.     // Compute (dx,dy) for (du,dv)=(1,0)
  579.  
  580.     #define dx_du    cos_angle_over_scale
  581.     #define    dy_du    -sin_angle_over_scale
  582.  
  583.     // Compute (dx,dy) for (du,dv)=(0,1)
  584.  
  585.     #define dx_dv    sin_angle_over_scale
  586.     #define    dy_dv    cos_angle_over_scale
  587.  
  588.     // Compute the first pixel in the destination surface (su, sv)
  589.  
  590.     int su = destrect->left - mx,
  591.         sv = destrect->top - my;
  592.  
  593.     // Compute the first pixel in the source surface (sx, sy)
  594.  
  595.     fix sx = cos_angle_over_scale * su + sin_angle_over_scale * sv,
  596.         sy = cos_angle_over_scale * sv - sin_angle_over_scale * su;
  597.  
  598.     // Transform to the source surface coordinates
  599.  
  600.     sx += srcsurf.dwWidth / 2;
  601.     sy += srcsurf.dwHeight / 2;
  602.     
  603.     // Do the blit
  604.             
  605.     for (int v = 0; v < h; v++)
  606.     {    
  607.         // (x,y) is the current pixel that has to be copied
  608.         
  609.         fix x = sx,
  610.             y = sy;
  611.  
  612.         for (int u = 0; u < w; u++, d += 4)
  613.         {
  614.             // (ix,iy) is the integer location of the current pixel
  615.  
  616.             int ix = (int)x, iy = (int)y;
  617.  
  618.             // Check if (ix,iy) is in the image
  619.  
  620.             if (ix >= 0 && ix < (int)srcsurf.dwWidth && iy >= 0 && iy < (int)srcsurf.dwHeight)
  621.             {
  622.                 // Compute the pixels location in memory
  623.                 
  624.                 s = ((BYTE *)srcsurf.lpSurface) + iy * srcsurf.lPitch + (ix << 2);
  625.  
  626.                 // If not mask_color then write the pixel
  627.  
  628.                 if (*(DWORD *)s != (DWORD)mask_color)
  629.                     *(DWORD *)d = *(DWORD *)s;
  630.             }
  631.  
  632.             // Update (x,y)
  633.  
  634.             x += dx_du;
  635.             y += dy_du;
  636.         }            
  637.         
  638.         // Update the destination pointer to the next scanline
  639.  
  640.         d += destsurf.lPitch - (w << 2);        
  641.  
  642.         // (sx,sy) is moved one scanline
  643.  
  644.         sx += dx_dv;
  645.         sy += dy_dv;
  646.     }
  647.  
  648.     // Unlock surfaces
  649.         
  650.     src->Unlock(0);
  651.     dest->Unlock(destrect);
  652. }
  653.